package com.itheima.service.impl;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mapper.EmpExprMapper;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.*;
import com.itheima.service.DeptService;
import com.itheima.service.EmpExprService;
import com.itheima.service.EmpLogService;
import com.itheima.service.EmpService;
import com.itheima.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
@Scope("singleton") //默认创建单例对象，可以省略不写,存放在ioc容器中，范围是IOC容器创建对象创建，IOC容器销毁对象销毁
//@Scope("prototype") //原型，多例创建对象，每次进行从容器里面获取一次创建一次对象，范围是获取的时候创建对象，交给开发者或者gc去销毁回收
//@Scope("request") //仅支持web环境中，对象创建存放在请求域中（一次请求内,没有存放在ioc容器中），前端请求开始创建请求对象HttpServletRequest,响应结束销毁对象。
                  //    写入请求域：request.setAttribute("empServiceImpl",对象)
                  //    读取请求域：request.getAttribute("empServiceImpl")
//@Scope("session") //仅支持web环境中，对象创建存放在会话域中（一个会话内,没有存放在ioc容器中），浏览器第一次访问服务器开始，直到浏览器或服务器关闭结束（服务器计算距离上一次请求超过30分钟销毁当前会话session对象）。
//    写入会话域：session.setAttribute("empServiceImpl",对象)
//    读取会话域：session.getAttribute("empServiceImpl")
//@Scope("application") //仅支持web环境中，对象创建存放在上下文域中（应用程序内,没有存放在ioc容器中），web服务器开始就创建对象，web服务器关闭就销毁对象。
//    写入上下文域：servletContext.setAttribute("empServiceImpl",对象)
//    读取上下文域：servletContext.getAttribute("empServiceImpl")
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {

    @Autowired
    private EmpMapper empMapper;
    @Autowired
    private EmpExprMapper empExprMapper;
    @Autowired
    private EmpExprService empExprService;
    @Autowired
    private EmpLogService empLogService;
    @Autowired
    private DeptService deptService;

    @Override
    public PageResult<Emp> page(EmpQueryParam empQueryParam) {
        // //1. 设置分页参数
        // PageHelper.startPage(empQueryParam.getPage(), empQueryParam.getPageSize());
        //
        // //2. 执行查询
        // List<Emp> empList = empMapper.list(empQueryParam);
        // Page<Emp> p = (Page<Emp>) empList;
        //
        // //3. 封装分页结果
        // return new PageResult<>(p.getTotal(), p.getResult());

        Page<Emp> empPage = new Page<>(empQueryParam.getPage(), empQueryParam.getPageSize());
        String name = empQueryParam.getName();
        Integer gender = empQueryParam.getGender();
        LocalDate begin = empQueryParam.getBegin();
        LocalDate end = empQueryParam.getEnd();
        lambdaQuery().like(!StrUtil.isEmpty(name), Emp::getName, name)
                .eq(!ObjUtil.isEmpty(gender), Emp::getGender, gender)
                .between(!ObjUtil.isEmpty(begin) && !ObjUtil.isEmpty(end),
                        Emp::getEntryDate, begin, end)
                .orderByAsc(Emp::getEntryDate)
                .page(empPage); // 这一步把分页结果放入empPage

        // 遍历获取部门id
        List<Integer> deptIds = empPage.getRecords().stream().map(Emp::getDeptId).distinct().toList();
        // 根据id获取部门数据
        List<Dept> deptList = deptService.listByIds(deptIds);
        // 替换empPage中的deptId
        empPage.getRecords().forEach(emp -> {
            Optional<Dept> op = deptList.stream()
                    .filter(dept -> dept.getId().equals(emp.getDeptId()))
                    .findFirst();
            if (op.isPresent()) {
                Dept dept = op.get();
                emp.setDeptName(dept.getName());
            }
        });
        // empPage.getRecords()就是查询到的一页的数据
        // 直接返回就可以
        return new PageResult<>(empPage.getTotal(), empPage.getRecords());
    }

    @Transactional(rollbackFor = Exception.class) //开启事务管理 - rollbackFor: 抛出什么异常回滚事务
    @Override
    public void saveEmp(Emp emp) throws Exception {
        // 1. 保存员工的基本信息
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        save(emp);
        log.info("保存员工信息, {}", emp);

        // 2. 保存工作经历信息
        List<EmpExpr> empExprList = emp.getExprList();
        if (empExprList != null && !empExprList.isEmpty()) {
            empExprList.forEach(empExpr -> empExpr.setEmpId(emp.getId()));
            empExprService.saveBatch(empExprList);
        }
    }

    @Override
    public List<Emp> list() {
        return empMapper.list(null);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Integer> ids) {
        lambdaUpdate().in(Emp::getId, ids).remove();
        log.info("删除员工信息,ids:{}", ids);
        empExprService.lambdaUpdate().in(EmpExpr::getEmpId, ids).remove();
        log.info("删除员工工作信息,ids:{}", ids);

    }

    @Override
    public Emp findById(Integer id) {
        Emp emp = getById(id);
        emp.setExprList(
                empExprService.lambdaQuery().eq(EmpExpr::getEmpId,id).list()
        );
        return emp;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(Emp emp) {
        // 更新员工信息
        emp.setUpdateTime(LocalDateTime.now());
        updateById(emp);

        // 更新员工的工作经历信息(先删除, 再添加)
        empExprService.lambdaUpdate().eq(EmpExpr::getEmpId, emp.getId()).remove();

        List<EmpExpr> empExprList = emp.getExprList();
        if(empExprList != null && !empExprList.isEmpty()) {
            empExprList.forEach(empExpr -> empExpr.setEmpId(emp.getId()));
            empExprService.saveBatch(empExprList);
        }
    }

    @Override
    public JobOption getEmpJobData() {
        // [{pos=教研主管, num=1} {pos=讲师, num=14}  {pos=学工主管, num=1} ...]
        List<Map> jobDataList = empMapper.getEmpJobData();

        // 组装数据 JobOption
        List jobList = jobDataList.stream().map(map -> {
            return map.get("pos");
        }).toList();

        List dataList = jobDataList.stream().map(map -> {
            return map.get("num");
        }).toList();
        return new JobOption(jobList, dataList);
    }


    @Override
    public List<Map<String, Object>> getEmpGenderData() {
        List<Map<String, Object>> mapList = empMapper.getEmpGenderData();
        return mapList;
    }

    /**
     * 根据用户名与密码查询员工登录信息
     * ctrl+Alt+鼠标点击，直接进入实现类重写方法中
     * @param emp
     * @return
     */
    @Override
    public LoginInfo getLoginInfo(Emp emp) {
        //1.根据用户名与密码查询员工信息Emp对象
        Emp e = empMapper.findByUserNameAndPwd(emp);

        if(e!=null) {
            //2.实例LoginInfo对象，封装数据返回
            LoginInfo loginInfo = new LoginInfo();
            loginInfo.setId(e.getId());
            loginInfo.setUsername(e.getUsername());
            loginInfo.setName(e.getName());

            //定义载荷
            Map<String,Object> claims = new HashMap<>();
            claims.put("id", e.getId());
            //调用工具类生成令牌
            String token = JwtUtils.generateJwt(claims);
            //封装令牌
            loginInfo.setToken(token);

            return loginInfo;
        }
        return null; //没有找到登录的员工
    }


}
